package com.yfjin.webrtc;

import android.content.Context;
import android.hardware.Camera;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.ByteBuffer;

import androidx.annotation.NonNull;

public class ManiuSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {

    static String TAG = "maniu";

    private Camera.Size size;
    private Camera mCamera;

    byte[] buffer;

    public ManiuSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        getHolder().addCallback(this);
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
        Log.i(TAG, "surfaceCreated");
        startPreview();
        initMediaCodec();
    }


    private void startPreview() {
        int num = Camera.getNumberOfCameras();
        mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        Camera.Parameters parameters = mCamera.getParameters();
        size = parameters.getPreviewSize();
        try {
            mCamera.setPreviewDisplay(getHolder());
//            横着
            mCamera.setDisplayOrientation(90);
            buffer = new byte[size.width * size.height * 3 / 2];
            mCamera.addCallbackBuffer(buffer);
            mCamera.setPreviewCallbackWithBuffer(this);
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {

    }

    private volatile boolean isCaptrue = true;

    public void startCaptrue() {
        isCaptrue = true;
    }

    //    画面    原始数据   编码  视频
//    @Override
//    public void onPreviewFrame(byte[] bytes, Camera camera) {
//        if (isCaptrue) {
//
//            isCaptrue = false;
//            Util.captrue(size, Util.ni(size, bytes));
//        }
//        mCamera.addCallbackBuffer(bytes);
//    }


    private MediaCodec mediaCodec;


    private void initMediaCodec() {

        try {
            mediaCodec = MediaCodec.createEncoderByType("video/avc");
        } catch (IOException e) {
            e.printStackTrace();
        }

        MediaFormat format = MediaFormat.createVideoFormat("video/avc", size.height, size.width);
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
        format.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
        format.setInteger(MediaFormat.KEY_BIT_RATE, 4000_000);
        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);

        mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mediaCodec.start();
    }


    byte[] nv21_rotated;

    @Override
    public void onPreviewFrame(byte[] bytes, Camera camera) {
        if (isCaptrue) {
            isCaptrue = false;
            Util.captrue(size, Util.ni(size, bytes));
        }

        nv21_rotated = Util.ni(size, bytes);
        byte[] temp = Util.nv21toNV12(nv21_rotated);

        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
        int inIndex = mediaCodec.dequeueInputBuffer(100 * 1000);

        if (inIndex >= 0) {
            ByteBuffer byteBuffer = mediaCodec.getInputBuffer(inIndex);
            byteBuffer.clear();
            byteBuffer.put(temp, 0, temp.length);
            mediaCodec.queueInputBuffer(inIndex, 0, temp.length, 0, 0);
        }

        int outIndex = mediaCodec.dequeueOutputBuffer(info, 100 * 1000);


        Log.i(TAG, "inIndex:" + inIndex + "---outIndex:" + outIndex + "--bytes:" + bytes.length + "-w:" + size.width + "-h:" + size.height);

        if (outIndex >= 0) {
            ByteBuffer bytebuffer = mediaCodec.getOutputBuffer(outIndex);
            byte[] ba = new byte[bytebuffer.remaining()];
            bytebuffer.get(ba);

//                writeContent(ba);
//                writeBytes(ba);


            mediaCodec.releaseOutputBuffer(outIndex, false);
        }

        mCamera.addCallbackBuffer(buffer);
    }


    public void writeBytes(byte[] array) {
        FileOutputStream writer = null;
        try {
            // 打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
            writer = new FileOutputStream(Environment.getExternalStorageDirectory() + "/camera.h264", true);
            writer.write(array);
            writer.write('\n');
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public String writeContent(byte[] array) {
        char[] HEX_CHAR_TABLE = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };
        StringBuilder sb = new StringBuilder();
        for (byte b : array) {
            sb.append(HEX_CHAR_TABLE[(b & 0xf0) >> 4]);
            sb.append(HEX_CHAR_TABLE[b & 0x0f]);
        }
        Log.i(TAG, "writeContent: " + sb.toString());
        FileWriter writer = null;
        try {
            // 打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
            writer = new FileWriter(Environment.getExternalStorageDirectory() + "/camera.txt", true);
            writer.write(sb.toString());
            writer.write("\n");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}
